package com.example.springbootsenior.StrategyMode;

import com.example.springbootsenior.StrategyMode.annotation.PayType;
import com.example.springbootsenior.StrategyMode.enums.PayTypeEnum;
import com.example.springbootsenior.StrategyMode.service.PayService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 功能描述:支付服务工厂
 *
 * @author: 李明杰
 * @date: 2021/11/24 21:08
 */
@Component
public class PayServiceFactory implements ApplicationContextAware {

    /**
     * 支付方式枚举-支付服务的映射集合
     */
    private static final Map<PayTypeEnum, PayService> payServiceMapping = new HashMap<>();

    /**
     * 工厂方法获取支付服务实现
     *
     * @param payTypeCode 支付方式的内部编码
     * @return 支付服务
     */
    public static final PayService getPayService(String payTypeCode) throws Exception {
        PayTypeEnum payTypeEnum = PayTypeEnum.getValue(payTypeCode);
        if (payTypeEnum == null) {
            throw new Exception("无效的支付编码");
        }
        PayService payService = payServiceMapping.get(payTypeEnum);
        if (payService == null) {
            throw new Exception("没有匹配的支付服务实现类");
        }
        return payService;
    }

    /**
     * 功能描述：初始化支付枚举-支付服务的映射<br>
     * setApplicationContext()会自动执行
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        Map<String, Object> payServiceMap = applicationContext.getBeansWithAnnotation(PayType.class);
        if (CollectionUtils.isEmpty(payServiceMap)) {
            try {
                throw new Exception("支付服务映射初始化失败");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        payServiceMap.forEach((key, bean) -> {
            if (!(bean instanceof PayService)) {
                try {
                    throw new Exception("注解：" + PayType.class + ",只能用于" + PayService.class + "的实现类中");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            PayService payService = (PayService) bean;
            PayType annotation = payService.getClass().getAnnotation(PayType.class);
            //annotation.value()注解上面指定的策略作为key【看着像方法，其实是属性】
            payServiceMapping.put(annotation.value(), payService);
        });
    }

}
